#include "game.h"
#include <iostream>
using namespace std;

void Game::initGame(){
    _instance = new Game();
    _instance -> initObjects();
}

void Game::initObjects(){
    vector2d position(300,300),size(20,400);
    createObject('w')
            -> setPosition(position)
            -> setSize(size)
            -> setState(LEFT);

    position.x(500);
    createObject('t')->setPosition(position);
}

TObject* Game::createObject(char type){
    static int counter = 0;
    counter++;
    TObject *p = NULL;
    switch(type){
    case 'w':
        p  = new TWall();
        break;
    case 't':
        p  = new TTank();
        break;
    case 'b':
        p  = new TBullet();
        break;
    }

    p -> setId(counter);
    objects.push_back(p);
    return p;
}

void Game::createInteraction(TObject* one, TObject* two){
    for(list<TObjectInteractor*>::iterator i = interactions.begin();i!=interactions.end();i++){
        TObjectInteractor& obj = **i;
        if(obj.pointsTo(one,two)){
            obj.setStillInteracting();
            return;
        }
    }
    interactions.push_back(new TObjectInteractor(one,two));
}

void Game::interact(){
    for(list<TObjectInteractor*>::iterator i = interactions.begin();i!=interactions.end();i++){
        TObjectInteractor& obj = **i;
        if(obj.IsStillInteracting()) obj.interact();
    }
}

TObject* Game::getUserObject(){
    for(TObjectIterator i = objects.begin();i!=objects.end();i++){
        TObject& obj = **i;
        if(obj.getType() == 't') return *i;
    }
    return NULL;
}


Game* Game::Instance(){
    return _instance;
}

void Game::triggerInteractions(){
    if(objects.size() >= 2) for(TObjectIterator a = objects.begin();a!=--objects.end();a++){
        TObject& obj1 = **a;

        for(TObjectIterator b = a++;b!=objects.end();b++){
            TObject& obj2 = **b;

            if(TObject::rectangleCollision(obj1,obj2))
                createInteraction(&obj1,&obj2);
        }
    }
}

void Game::move(QPainter& painter){
    for(TObjectIterator i = objects.begin();i!=objects.end();i++){
        TObject& obj = **i;

        if(!obj.checkIfAlive()) continue;

        obj.getGraphic() -> hide(painter);
        obj.tick();
        obj.getGraphic() -> paint(painter);
    }
}

void Game::erase(){
    if(objects.size() >= 1) for(TObjectIterator i = objects.begin();i!=objects.end();){
        TObject& obj = **i;

        if(!obj.checkIfAlive()){
            i = objects.erase(i);
        }else{
            i++;
        }
    }
}

void Game::tick(QPainter& painter){
    triggerInteractions();
    interact();
    move(painter);
    erase();
}

const char * Game::read(){
    QString res;
    for(TObjectIterator i = objects.begin();i!=objects.end();i++){
        TObject& obj = **i;
        res += obj.dump() + "|";
    }

    return res.toUtf8().constData();
}

void Game::write(char * data){
    cout << "Данные, полученые от сервера: " << data << "\n";
}



Game* Game::_instance = NULL;

Game::Game(){
    _painter = NULL;
}

Game::Game(Game const&){

}

Game& Game::operator=(Game const&){
    return *_instance;
}
